package com.keya.utils;

import cn.hutool.crypto.digest.MD5;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

@Slf4j
public class MD5Utils {

    private static final int POOL_SIZE = 4;

    private static ExecutorService executor;

    private static ExecutorService getPool() {
        if (executor == null) {
            executor = Executors.newFixedThreadPool(POOL_SIZE);
        }
        return executor;
    }

    public static String md5(String path) {
        long l = System.currentTimeMillis();
        File file = new File(path);
        if (!file.exists()) return null;
        List<String> md5s = md5Recursion(file);
        Collections.sort(md5s);
        String md5Str = String.join("", md5s);
        long l1 = System.currentTimeMillis();
        log.info("计算md5耗时" + (l1 - l) + "ms" + ", count="+md5s.size());
        return MD5.create().digestHex(md5Str);
    }

    private static List<String> md5Recursion(File file) {
        List<Future<String>> results = new ArrayList<>();
        try {
            Files.walk(file.toPath()).forEach(p -> {
                File f = p.toFile();
                if (f.isFile()) {
                    results.add(getPool().submit(() -> MD5.create().digestHex(f)));
                }
            });
            List<String> md5s = new ArrayList<>(results.size());
            for (Future<String> future : results) {
                md5s.add(future.get());
            }
            return md5s;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
